using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;


namespace Contact_Manager
{
    public partial class ContactManager : Form
    {
        //private string filePath;
        //public string FilePath
        //{
        //    get { return filePath; }
        //    set { filePath = value; }
        //}

        public string Delimiters
        {
            get { return Properties.Settings.Default.Delimiters; }
        }

        public string FileContact
        {
            get { return Properties.Settings.Default.File; }
            set { Properties.Settings.Default.File = value;
                  Properties.Settings.Default.Save();      }
        }

        private ArrayList contacts;
        public ArrayList Contacts
        {
            get { return contacts; }
        }

        private ArrayList curContacts;
        public ArrayList CurContacts
        {
            get { return curContacts; }
        }

        private string format;
        public string Format
        {
            get { return format; }
            set { format = value; }
        }

        public string rtbText
        {
            get { return rtb.Text; }
            set { rtb.Text = value; }
        }

        public void AddRtbText(string s)
        {
            rtb.Text = s + rtb.Text;
            this.SaveContactArray();
            this.SaveContactFile();
        }

        private string startFile = "";

        public ContactManager()
        {
            InitializeComponent();
        }

        public ContactManager(string s)
        {
            InitializeComponent();
            this.FileContact = s;
            this.startFile = s;
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Control)
                if (e.KeyCode.ToString() == "F") this.txtSearch.Focus();
                else if (e.KeyCode.ToString() == "E") this.rtb.Focus();
                else if (e.KeyCode.ToString() == "W") this.Close();
        }

        private void ContactManager_Load(object sender, EventArgs e)
        {
            contacts = new ArrayList ();
            curContacts = new ArrayList ();
            chkAuto.Checked = Properties.Settings.Default.AutoSearch;
            chkCase.Checked = Properties.Settings.Default.CaseSensitive;
            chkWordWrap.Checked = Properties.Settings.Default.WordWrap;
            chkSuggest.Checked = Properties.Settings.Default.Suggest;

            format = "<Name>, <Emails>, <Phones>, <Descriptions>";

            // Set these when the form loads:
            // Have the form capture keyboard events first.
            this.KeyPreview = true;
            // Assign the event handler to the form.
            this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);

            if (this.startFile != "") this.FileContact = this.startFile;
            this.LoadContactFile();
        }

        private void LoadContactFile()
        {
            contacts.Clear();
            try
            {
                StreamReader fr = new StreamReader(this.FileContact);
                string line;
                StringBuilder sb = new StringBuilder();
                int count = 0;
                while ((line = fr.ReadLine()) != null)
                {
                    if (line.Trim() != "")
                    {
                        contacts.Add(new Contact(line, Delimiters));
                        curContacts.Add(count);
                        count++;
                    }
                    sb.AppendLine(line + "\n");
                }
                //sb.Append(fr.ReadToEnd());
                //contacts.AddRange(sb.ToString().Split(Environment.NewLine.ToCharArray()));
                this.rtb.Text = sb.ToString();
                fr.Close();
                //AutoCompleteStringCollection autoString = new AutoCompleteStringCollection();                
                //for (int i = 0; i < contacts.Count; i++)
                //{
                //    string[] s = (((Contact)contacts[i]).Line).Split(Delimiters.ToCharArray());
                //    for (int j = 0; j < s.Length; j++)
                //        if (s[j].Trim() != "")
                //        {
                //            int k = 0;
                //            while (k >= 0)
                //            {
                //                if (k >= 0) autoString.Add(s[j].Substring(k).Trim());
                //                k = s[j].IndexOf(' ', k + 1);
                //            }
                //        }
                //}
                ////autoString.AddRange((string[])contacts.ToArray(typeof(string)));
                //this.txtSearch.AutoCompleteCustomSource = autoString;
                //this.CheckSuggest();

                this.Text = "Simple Contact Manager - " + FileContact;
            }
            catch (Exception e)
            {
            }
        }

        private void txtSearch_TextChanged(object sender, EventArgs e)
        {
            if (chkAuto.Checked) this.Search();
        }

        private void btnSetting_Click(object sender, EventArgs e)
        {
            SettingForm frmSetting = new SettingForm();
            frmSetting.ShowDialog(this);
        }

        public string WildcardToRegex(string pattern)
        {
            return Regex.Escape(pattern).
             Replace("\\*", ".*").
             Replace("\\?", ".");
        }

        private bool RelevantAnd(string contact, string txt, bool CaseSen)
        {
            string[] terms = txt.Split("&".ToCharArray());
            //if (!CaseSen)
            //{
            //    contact = contact.ToLower();
            //    for (int i = 0; i < terms.Length; i++) terms[i] = terms[i].ToLower();
            //}
            for (int i = 0; i < terms.Length; i++)
            {
                bool not = false;
                terms[i] = terms[i].Trim();
                while (terms[i].StartsWith("!"))
                {
                    not = !not; terms[i] = terms[i].Remove(0, 1).Trim();
                }

                bool relevant;
                if (!CaseSen)
                    relevant = Regex.IsMatch(contact, WildcardToRegex(terms[i]), RegexOptions.IgnoreCase);
                else
                    relevant = Regex.IsMatch(contact, WildcardToRegex(terms[i]));

                if (!not) { if (!relevant) return false; } else { if (relevant) return false; }
            }
            return true;
        }

        private bool RelevantOr(string contact, string txt, bool CaseSen)
        {
            string[] searchTermsAnd = txt.Split("|".ToCharArray());
            for (int i = 0; i < searchTermsAnd.Length; i++)
                if (RelevantAnd(contact, searchTermsAnd[i], CaseSen)) return true;
            return false;
        }

        private void Search()
        {
            curContacts.Clear();
            StringBuilder sb = new StringBuilder();
            string txt = txtSearch.Text;
            for (int i = 0; i < contacts.Count; i++)
            {
                string s = ((Contact)contacts[i]).Line;
                if (RelevantOr(s, txt, chkCase.Checked))
                {
                    sb.AppendLine(s + "\n");
                    if (s.Trim() != "") curContacts.Add(i);
                }
            }
            rtb.Text = sb.ToString();
            //Font font = new Font("Arial", 10, FontStyle.Bold);
            //if (rtb.Text.Length > 0)
            //{
            //    int i = 0;
            //    do
            //    {
            //        i = rtb.Find(txt, i + 1, RichTextBoxFinds.None);
            //        rtb.SelectionFont = font;
            //    }
            //    while (i > 0);
            //}
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            this.Search();
        }

        private void txtSearch_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter) this.Search();
        }

        //private void ContactManager_Activated(object sender, EventArgs e)
        //{
        //    if (this.FilePath != FileContact)
        //    {
        //        this.FilePath = FileContact;
        //        LoadContactFile();
        //        this.txtSearch.Focus();
        //    }
        //}

        private void SaveContactFile()
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < contacts.Count; i++)
            {
                sb.AppendLine(((Contact)contacts[i]).Line);
            }
            BackUpFile(FileContact);
            try
            {
                StreamWriter fw = new StreamWriter(FileContact);
                fw.Write(sb.ToString());
                fw.Close();
            }
            catch { }
        }

        private void SaveContactArray()
        {
            ArrayList  newContacts = new ArrayList ();
            string[] lines = rtb.Lines;
            int count = 0;
            for (int i = 0; (i < curContacts.Count) || (i < lines.Length); i++)
            {
                while ((count < lines.Length) && (lines[count].Trim() == "")) count++;
                if (count < lines.Length)
                {
                    if (i >= curContacts.Count)
                    {
                        newContacts.Add(contacts.Count);
                        contacts.Add(new Contact(lines[count], Delimiters));
                    }
                    else
                    {
                        int k = (int)curContacts[i];
                        newContacts.Add(k);
                        contacts[k] = new Contact(lines[count], Delimiters);
                    }
                    count++;
                }
                else
                    if (i < curContacts.Count)
                    {
                        int k = (int)curContacts[i];
                        contacts.RemoveAt(k);
                        for (int j = 0; j < newContacts.Count; j++)
                            if ((int)newContacts[j] >= k) newContacts[j] = (int)newContacts[j] - 1;
                        for (int j = 0; j < curContacts.Count; j++)
                            if ((int)curContacts[j] >= k) curContacts[j] = (int)curContacts[j] - 1;
                    }
            }
            curContacts = newContacts;
        }

        private void btnUpdate_Click(object sender, EventArgs e)
        {
            SaveContactArray();
            SaveContactFile();
        }

        private void chkAuto_CheckedChanged(object sender, EventArgs e)
        {
            Properties.Settings.Default.AutoSearch = chkAuto.Checked;
            Properties.Settings.Default.Save();
            if (chkAuto.Checked) this.Search();
        }

        private void chkCase_CheckedChanged(object sender, EventArgs e)
        {
            Properties.Settings.Default.CaseSensitive = chkCase.Checked;
            Properties.Settings.Default.Save();
            this.Search();
        }

        private void chkWordWrap_CheckedChanged(object sender, EventArgs e)
        {
            this.rtb.WordWrap = this.chkWordWrap.Checked;
            Properties.Settings.Default.WordWrap = chkWordWrap.Checked;
            Properties.Settings.Default.Save();
        }

        private void CheckSuggest()
        {
            if (chkSuggest.Checked) this.txtSearch.AutoCompleteMode = AutoCompleteMode.Suggest;
            else this.txtSearch.AutoCompleteMode = AutoCompleteMode.None;
        }

        private void chkSuggest_CheckedChanged(object sender, EventArgs e)
        {
            CheckSuggest();
            Properties.Settings.Default.Suggest = chkSuggest.Checked;
            Properties.Settings.Default.Save();
        }

        private void btnEmail_Click(object sender, EventArgs e)
        {
            string mail = "mailto:"; // "mailto:user@domain.com?subject=subject text";
            for (int i = 0; i < curContacts.Count; i++)
            {
                ArrayList arrNames = ((Contact)contacts[(int)curContacts[i]]).Names;
                ArrayList arrEmails = ((Contact)contacts[(int)curContacts[i]]).Emails;
                if ((arrEmails.Count > 0)) 
                {
                    if (arrNames.Count > 0)
                        mail += (string)arrNames[0] + " <" + (string)arrEmails[0] + ">,";
                    else
                        mail += (string)arrEmails[0] + ",";
                    if (mail.Length > 1500) break;
                }
            }
            System.Diagnostics.Process.Start(mail);            
        }

        private void btnExport_Click(object sender, EventArgs e)
        {
            Export frmEx = new Export();
            frmEx.Format = this.Format;
            frmEx.ShowDialog(this);
        }

        private void btnImport_Click(object sender, EventArgs e)
        {
            Import frmIm = new Import();
            frmIm.ShowDialog(this);
        }

        private void BackUpFile(string file)
        {
            File.Copy(file, file + ".bak", true);
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            OpenFileDialog fileDialog = new OpenFileDialog();
            if (fileDialog.ShowDialog(this) == DialogResult.OK)
            {
                this.FileContact = fileDialog.FileName;
                this.LoadContactFile();
            }
        }

        private void ContactManager_DragDrop(object sender, DragEventArgs e)
        {
            try
            {
                this.FileContact = ((Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
                this.LoadContactFile();
            }
            catch { }
        }

        private void ContactManager_DragOver(object sender, DragEventArgs e)
        {
            if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move)
            {
                // By default, the drop action should be move, if allowed.
                e.Effect = DragDropEffects.Move; // <<<=--------------- HERE!
            }
        }

    }
}